#include "../logs/util.hpp"
#include "../logs/level.hpp"
#include "../logs/sink.hpp"
#include "../logs/format.hpp"
#include "../logs/logger.hpp"
#include "../logs/buffer.hpp"
#include "../logs/mylog.h"

void TestUtil()
{
    std::cout << mian_yang::util::Date::getTime() << std::endl;
    mian_yang::util::File newfile;
    std::string pathname = "./new/file/sdf";
    std::cout << newfile.path(pathname) << std::endl;
    std::cout << newfile.exists(pathname) << std::endl;
    std::cout << pathname << std::endl;
    newfile.createDirectory(pathname);
    std::cout << newfile.exists(pathname) << std::endl;
}

/*读取文件数据， 一点一点写入缓冲区， 最终将缓冲区数据写入文件， 判断生成的新文件与源文件是否一致*/
void TestBuffer()
{
    std::ifstream ifs("./logfile/test.log/file.log", std::ios::binary); // 创建写文件， 二进制写
    if (ifs.is_open() == false)
    {
        return;
    }
    ifs.seekg(0, std::ios::end); // 读写位置跳转到文件末尾
    size_t fsize = ifs.tellg();  // 获得当前读写位置相对于起始位置的偏移量
    ifs.seekg(0, std::ios::beg); // 重新跳转到起始位置
    std::string body;            // 定义一个
    body.resize(fsize);
    ifs.read(&body[0], fsize);
    if (ifs.good() == false)
    {
        std::cout << "read error\n";
        return;
    }
    ifs.close();

    mian_yang::Buffer buffer;
    for (int i = 0; i < body.size(); i++)
    {
        buffer.push(&body[i], 1);
    }

    std::ofstream ofs("./logs/tmp.log", std::ios::binary);
    ofs.write(buffer.begin(), buffer.readAbleSize());
    // for (int i = 0; i < buffer.readAbleSize(); i++)
    // {
    //     ofs.write(buffer.begin(), 1);
    //     buffer.moveReader(1);
    // }
    ofs.close();
}

void TestSink()
{
    mian_yang::LogMsg msg("main.cc", 12, "logger", "正在进行格式测试....", mian_yang::LogLevel::value::DEBUG);
    mian_yang::Formatter fmt("[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");

    /*拿到日志消息， 然后创建格式化对象， 根据格式化对象对日志消息进行格式化。 得到的
      字符串就是最后的结果， 然后这个结果由落地对象进行打印。
      所以流程就是： 拿到消息——》格式化——》交给落地对象打印*/
    std::string str = fmt.format(msg); //

    mian_yang::StdoutSink::ptr StdLsp = mian_yang::SinkFactory<mian_yang::StdoutSink>::create();
    mian_yang::FileSink::ptr FileLsp = mian_yang::SinkFactory<mian_yang::FileSink>::create("./logfile/test.log/file.log");
    mian_yang::RollSink::ptr RollLsp = mian_yang::SinkFactory<mian_yang::RollSink>::create("./logfile/test.log/roll-", 1024 * 1024);
    mian_yang::RollByTimeSink::ptr TimeLsp =
        mian_yang::SinkFactory<mian_yang::RollByTimeSink>::create("./logfile/test.log/rolltime-", mian_yang::TimeGap::GAP_SECOND);

    // StdLsp->log(str.c_str(), str.size());
    // FileLsp->log(str.c_str(), str.size());
    // int count = 0;
    // int cur_size = 0;
    // while (cur_size < 1024 * 1024 * 10)
    // {
    //     std::string tmp = std::to_string(count++) + str;
    //     RollLsp->log(tmp.c_str(), tmp.size());
    //     cur_size += tmp.size();
    // }

    time_t old = mian_yang::util::Date::getTime();

    while (mian_yang::util::Date::getTime() < old + 5)
    {
        TimeLsp->log(str.c_str(), str.size());
    }
}

void TestFormat()
{
    mian_yang::LogMsg msg(__FILE__, __LINE__, "logger", "正在进行格式测试....", mian_yang::LogLevel::value::DEBUG);
    mian_yang::Formatter fmt;
    std::string str = fmt.format(msg);
    std::cout << str << std::endl;
}

void Test1Logger()
{
    const std::string Logger_name = "sync_logger";                              // 定义日志器名称
    mian_yang::LogLevel::value Logger_level = mian_yang::LogLevel::value::WARN; // 设置限制等级为WARN
    mian_yang::Formatter::ptr fmt(new mian_yang::Formatter());                  // 日志格式设置

    /*这里创建三种落地方式， 其实就是多态的应用。 这里都是使用LogSink类型的智能指针指向子类的对象， 调用的是子类重写的虚函数*/
    mian_yang::StdoutSink::ptr StdLsp = mian_yang::SinkFactory<mian_yang::StdoutSink>::create();
    mian_yang::FileSink::ptr FileLsp = mian_yang::SinkFactory<mian_yang::FileSink>::create("./logfile/test.log/file.log");
    mian_yang::RollSink::ptr RollLsp = mian_yang::SinkFactory<mian_yang::RollSink>::create("./logfile/test.log/roll-", 1024 * 1024);

    std::vector<mian_yang::LogSink::ptr> sinks = {RollLsp, FileLsp, StdLsp};

    // 然后创建日志器， 将这些信息整合起来//这里是智能指针， 那么就是使用new对象初始化。没有问题，
    mian_yang::Logger::ptr Logger_ptr(new mian_yang::SyncLogger(Logger_name, Logger_level, fmt, sinks));

    int cnt = 0;
    while (cnt <= 5 * 10000)
    {
        Logger_ptr->fatal(__FILE__, __LINE__, "日志消息——%d", cnt);
        cnt++;
    }
}

void Test2Logger()
{
    std::unique_ptr<mian_yang::LoggerBuilder> Lgbder(new mian_yang::LocallLoggerBuilder()); /*不允许抽象类型创建对象， 那么可以使用抽象指针。*/
    Lgbder->buildLoggerName("sync_logger");
    Lgbder->buildLoggerLevel(mian_yang::LogLevel::value::WARN);
    Lgbder->buildFormatter();
    Lgbder->buildLoggerType(mian_yang::LoggerType::LOGGER_SYNC);
    Lgbder->buildSink<mian_yang::FileSink>("./logfile/test.log/file.log");
    Lgbder->buildSink<mian_yang::RollSink>("./logfile/test.log/roll-", 1024 * 1024);
    mian_yang::Logger::ptr Logger_ptr = Lgbder->build();

    int cnt = 0;
    while (cnt <= 2 * 10000)
    {
        Logger_ptr->fatal(__FILE__, __LINE__, "日志消息——%d", cnt);
        cnt++;
    }
}

void Test3Logger()
{
    std::unique_ptr<mian_yang::LoggerBuilder> Lgbder(new mian_yang::LocallLoggerBuilder()); /*不允许抽象类型创建对象， 那么可以使用抽象指针。*/
    Lgbder->buildLoggerName("async_logger");
    Lgbder->buildLoggerLevel(mian_yang::LogLevel::value::WARN);
    Lgbder->buildFormatter();
    Lgbder->buildLoggerType(mian_yang::LoggerType::LOGGER_ASYNC);
    Lgbder->buildSink<mian_yang::FileSink>("./logfile/test.log/file.log");
    Lgbder->buildSink<mian_yang::RollSink>("./logfile/test.log/roll-", 1024 * 1024);
    mian_yang::Logger::ptr Logger_ptr = Lgbder->build();

    int cnt = 0;
    while (cnt <= 50 * 10000)
    {
        Logger_ptr->fatal(__FILE__, __LINE__, "日志消息——%d", cnt);
        cnt++;
    }
}
void _Test4Logger()
{
    mian_yang::Logger::ptr Logger_ptr = mian_yang::LoggerManager::GetInstance().getLogger("async_logger");
    int cnt = 0;
    while (cnt <= 50 * 10000)
    {
        Logger_ptr->fatal(__FILE__, __LINE__, "日志消息——%d", cnt);
        cnt++;
    }
}

void Test4Logger()
{
    /*创建一个工厂， 这个工厂是全局工厂。 */                                                /*利用*全局工厂初始化工厂*/
    std::unique_ptr<mian_yang::LoggerBuilder> Lgbder(new mian_yang::GlobalLoggerBuilder()); /*不允许抽象类型创建对象， 那么可以使用抽象指针。*/

    /*全局工厂各项属性进行初始化*/
    Lgbder->buildLoggerName("async_logger");
    Lgbder->buildLoggerLevel(mian_yang::LogLevel::value::WARN);
    Lgbder->buildFormatter();
    Lgbder->buildLoggerType(mian_yang::LoggerType::LOGGER_ASYNC);
    Lgbder->buildSink<mian_yang::StdoutSink>();
    Lgbder->buildSink<mian_yang::FileSink>("./logfile/test.log/file.log");
    Lgbder->buildSink<mian_yang::RollSink>("./logfile/test.log/roll-", 1024 * 1024);
    Lgbder->build();
    _Test4Logger();
}

void Testmylog()
{
    int cnt = 0;
    while (cnt < 50000)
    {
        DEBUG("测试日志%d", cnt++);
    }


}

int main()
{
    // mian_yang::util::TestUtil();  //测试使用工具类
    // mian_yang::LogLevel::TestLevel();  //测试日志等级的打印

    // mian_yang::Formatter::TestFormat();
    // TestSink();
    // Test1Logger();
    // Test2Logger();
    // Test1Logger();
    // TestBuffer();
    // Test3Logger();
    // Test4Logger();
    Testmylog();


    return 0;
}
